package com.tangsm.spring.boot.api.http;

import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 请求缓存包装器
 *
 * @author tangsm
 */
public class CacheRequestWrapper extends HttpServletRequestWrapper {

    /**
     * body数据
     */
    private byte[] body;

    /**
     * 获取body数据
     *
     * @return byte[]
     */
    public byte[] getBody() {
        return body;
    }

    /**
     * 有参构造
     *
     * @param request http请求信息
     * @throws IOException      IOException
     * @throws ServletException ServletException
     */
    public CacheRequestWrapper(HttpServletRequest request) throws IOException, ServletException {
        super(request);
        ServletInputStream inputStream = request.getInputStream();
        String header = request.getHeader("Content-Length");
        if (header == null) {
            return;
        }
        int contentLength = Integer.parseInt(header);
        byte[] bytes = new byte[contentLength];
        int readCount = 0;
        while (readCount < contentLength) {
            readCount += inputStream.read(bytes, readCount, contentLength - readCount);
        }
        body = bytes;
    }

    /**
     * 重写getInputStream()读取缓存body获取ServletInputStream
     *
     * @return ServletInputStream对象包含请求的body
     * @throws IOException 如果发生输入或输出异常
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return inputStream.available() == 0;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return inputStream.read();
            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}
